package org.gosdt.ew.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.gosdt.ew.model.Alphabet;
import org.gosdt.ew.model.Topic;
import org.gosdt.ew.model.Vocabulary;

/**
 * Vocabulary form, has follow ability:<br>
 * <ol>
 * <li>allow to select words:
 * 		<ol>
 * 			<li>by selected topic</li>
 * 			<li>by whole interpretation or word</li>
 * 			<li>by part interpretation or word</li>
 * 		</ol>
 * </li>
 * <li> allow to call form for adding new words </li>
 * <li> allow to change topic dependents for word </li>
 *  
 * @author anton
 */
public class AddToTopicForm extends BaseForm {

	private static final long serialVersionUID = 1L;
	
	private JCheckBox jcbIsTransleat;
	private JCheckBox jcbIsNotWholeWord;
	private JComboBox jcbFindedWords;
	private JLabel jtfErrors;
	private JLabel jtfEditWords;
	
	private JList jltAvalableTopic;
	private DefaultListModel model;
	private JScrollPane jspTopic;
	private ArrayList<Topic> topicList;
	private ArrayList<Topic> wordTopics;
	private ArrayList<Vocabulary> wordsList;
	
	private JButton jbtClose;
	private JButton jbtSave;
	private JButton jbtShowCard;
	private JButton jbtAddWords;
	
	private JPanel jpnAvailableActions;
	private JPanel jpnAvailableSettings;
	
	/**
	 * Constructor of form
	 * @param parent	-	main form for this window
	 */
	public AddToTopicForm(JFrame parent){
		super(parent, "add words to topics");
		doInitForm();
		this.setVisible(true);
	}

	@Override
	protected void doInitForm() {
		doInitAllComponents();
		setLabelsName();
		this.setLayout(new BorderLayout());
		jcbFindedWords.setEditable(true);
		
		int width = myParent.getWidth() - 10;
		int magic = 210; // count of pixel for good button
		int height = 25;
		
		jtfErrors.setBounds(5, 5, width, 20);
		jcbIsTransleat.setBounds(5, 20, width, 20);
		jcbIsNotWholeWord.setBounds(5, 40, width, 20);
		jbtAddWords.setBounds(5, 60, width, height);
		jtfEditWords.setBounds(5, 85, width, 20);
		jcbFindedWords.setBounds(5, 105, width, height);
		jbtShowCard.setBounds(5, 135, width, height);
		jspTopic.setBounds(5, 165, width, height*3);
		
		jpnAvailableSettings.add(jtfErrors);
		jpnAvailableSettings.add(jcbIsTransleat);
		jpnAvailableSettings.add(jcbIsNotWholeWord);
		jpnAvailableSettings.add(jtfEditWords);
		jpnAvailableSettings.add(jbtShowCard);
		jpnAvailableSettings.add(jcbFindedWords);
		jpnAvailableSettings.add(jspTopic);
		jpnAvailableSettings.add(jbtAddWords);
		
		if (width <= magic){
			jbtClose.setPreferredSize(new Dimension((int)(width * 0.47), 25));
			jbtSave.setPreferredSize(new Dimension((int)(width * 0.47), 25));
			jpnAvailableActions.setLayout(new FlowLayout(FlowLayout.CENTER, (int)(width * 0.02), 0));
		}
		jpnAvailableActions.add(jbtClose);
		jpnAvailableActions.add(jbtSave);
		
		this.add(jpnAvailableActions, BorderLayout.SOUTH);
		this.add(jpnAvailableSettings, BorderLayout.CENTER);
		setButtonListeners();		

	}

	@Override
	protected void setButtonListeners() {

		jbtClose.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				doClose();
			}
		});
		
		jbtSave.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				saveTopics();
			}
		});
		
		jbtShowCard.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (jcbFindedWords.getSelectedItem().toString().equals("")){
					JOptionPane.showMessageDialog(myParent, "необходимо выбрать слово");
					return;
				}
				myParent.changeTimerStatus();
				new NewLessonForm(myParent, wordsList.get(jcbFindedWords.getSelectedIndex()));
				myParent.changeTimerStatus();
			}
		});
		
		jcbFindedWords.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if (jcbFindedWords.getSelectedItem() == null)
					return;
				if (jcbFindedWords.getSelectedItem().toString().equals("") & !jcbIsNotWholeWord.isSelected())
					return;
				setBusyCursor();
				if (jcbFindedWords.getSelectedIndex() > -1)
					doSelectionByWordsTopic();
				else{
					if (jcbFindedWords.getSelectedObjects() == null)
						return;
					doSelectByOptions();
				}
				setNormalCursor();
			}
		});
		
		jltAvalableTopic.addListSelectionListener(new ListSelectionListener() {
			
			@Override
			public void valueChanged(ListSelectionEvent arg0) {
				if ((jcbFindedWords.getSelectedIndex() == -1) & 
						(jltAvalableTopic.getSelectedIndices().length == 1))
				{
					try{
						setBusyCursor();
						Vocabulary voc = new Vocabulary(new Alphabet(myParent.getProfile().getStudyLanguage(), ""));
						voc.mySelect.topicName = topicList.get(jltAvalableTopic.getSelectedIndex()).getTopicName();
						voc.mySelect.setLanguage(myParent.getProfile().getStudyLanguage());
						jtfErrors.setText("слова в теме: " + voc.mySelect.getTopicName());
						wordsList = voc.getList(voc.mySelect);
						if (jcbFindedWords.getItemCount() > 0)
							jcbFindedWords.removeAllItems();
						fillWordComboBox();
					}
					finally{
						setNormalCursor();
					}
				}
				
			}
		});
		
		jbtAddWords.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				myParent.changeTimerStatus();
				myParent.callNewLessonForm();
				myParent.changeTimerStatus();
			}
		});
	}
	
	/**
	 * change cursor to busy one
	 */
	private void setBusyCursor(){
		this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
	}
	/**
	 * change cursor to normal
	 */
	private void setNormalCursor(){
		this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}

	@Override
	protected void setLabelsName() {
		this.setTitle(myParent.getTitle() + " - Add word to topic");
		jbtClose.setText("Закрыть");
		jbtSave.setText("Сохоанить");
		
		jcbIsTransleat.setText("Искать по переводу");
		jcbIsNotWholeWord.setText("Искать по части слова");
		jtfEditWords.setText("Поле для поиска");
		jbtShowCard.setText("Показать карточку слова");
		jbtAddWords.setText("Добавить слова");
		
		jtfErrors.setForeground(Color.RED);
		fillTopicList();
	}
	
	/**
	 * Create forms components
	 */
	private void doInitAllComponents(){
		
		jcbIsTransleat = new JCheckBox();
		jcbIsNotWholeWord = new JCheckBox();
		jcbFindedWords = new JComboBox();
		jtfEditWords = new JLabel();
		jtfErrors = new JLabel();
		
		model = new DefaultListModel();
		jltAvalableTopic = new JList(model);
		jltAvalableTopic.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		jspTopic = new JScrollPane(jltAvalableTopic, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		topicList = new ArrayList<Topic>();
		
		jbtClose = new JButton();
		jbtSave = new JButton();
		jbtShowCard = new JButton();
		jbtAddWords = new JButton();
		
		jpnAvailableActions = new JPanel();
		jpnAvailableSettings = new JPanel(null);
	}
	
	/**
	 * Detach events listeners and dispose current form
	 */
	private void doClose(){
		jbtClose.removeActionListener(jbtClose.getActionListeners()[0]);
		jbtSave.removeActionListener(jbtSave.getActionListeners()[0]);
		jcbFindedWords.removeActionListener(jcbFindedWords.getActionListeners()[0]);
		jcbFindedWords.removeItemListener(jcbFindedWords.getItemListeners()[0]);
		jbtShowCard.removeActionListener(jbtShowCard.getActionListeners()[0]);
		myParent.changeTimerStatus();
		this.dispose();
	}
	
	/**
	 * select words list by selected options on form
	 */
	private void doSelectByOptions(){
		if (wordsList == null){
			wordsList = new ArrayList<Vocabulary>();
		}
		else {
			wordsList.clear();
		}
		Vocabulary voc = new Vocabulary(new Alphabet(myParent.getProfile().getStudyLanguage(), ""));
		fillSelectStructure(voc);
		wordsList = voc.getList(voc.mySelect);
		if (jcbFindedWords.getItemCount() > 0)
			jcbFindedWords.removeAllItems();
		fillWordComboBox();
	}
	
	/**
	 * prepare sql select fore executing
	 * @param word - current word
	 */
	private void fillSelectStructure(Vocabulary word){
		String operator = "=";
		String value = jcbFindedWords.getSelectedItem().toString();
		
		if (jcbIsNotWholeWord.isSelected()){
			operator = "like";
			value = "%" + value + "%";
		}
			
		if (jcbIsTransleat.isSelected()){
			word.mySelect.setInterpretationValue(value);
			word.mySelect.setSqlInterpretationOperator(operator);
		}
		else{
			word.mySelect.setWordValue(value);
			word.mySelect.setSqlWordOperator(operator);
		}
		
		word.mySelect.setLanguage(myParent.getProfile().getStudyLanguage());
	}
	
	/**
	 * fill selected words for user needs
	 */
	private void fillWordComboBox(){
		if (wordsList == null)
			return;

		for (int i = 0; i < wordsList.size(); i++) {
			jcbFindedWords.addItem(wordsList.get(i).getWord());
		}
	}
	
	/**
	 * fill all available topics for current language
	 */
	private void fillTopicList(){
		topicList = Topic.getTopicList("<>", "''", myParent.getProfile().getStudyLanguage());
		for (int i = 0; i < topicList.size(); i++) {
			model.add(i, topicList.get(i).getTopicName());
		} 
	}
	
	/**
	 * select topics for one selected word
	 */
	private void fillTopicListForWord(){
		wordTopics = Topic.getTopicListByWord("=", Integer.toString(wordsList.get(jcbFindedWords.getSelectedIndex()).getId()));
	}
	
	/**
	 * select words by selected topic
	 */
	private void doSelectionByWordsTopic(){
		fillTopicListForWord();
		int[] size = new int[wordTopics.size()];
		for (int i = 0; i < wordTopics.size(); i++) {
			int ind = topicList.indexOf(wordTopics.get(i));
			size[i] = ind;
		}
		jltAvalableTopic.setSelectedIndices(size);
	}
	
	/**
	 * save changes in word and topics relations
	 */
	private void saveTopics(){
		for (Topic topic : wordTopics) {
			topic.deleteWordsTopics(wordsList.get(jcbFindedWords.getSelectedIndex()));
		}
		addTopicsToWord(wordsList.get(jcbFindedWords.getSelectedIndex()));
	}

	/**
	 * commit changes
	 * @param word - word for changes
	 */
	private void addTopicsToWord(Vocabulary word){
		int[] topics = jltAvalableTopic.getSelectedIndices();
		for (int i = 0; i < topics.length; i++) {
			Topic topic = topicList.get(topics[i]);
			word.setTopicToWord(topic);
			word.updateCurrentRecord();
		}
	}
		

}
